﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;    //线程使用
using System.Net;          //网络使用
using System.Net.Sockets;  //socket使用

namespace TestFireBroadcastingHostPhone.RelatedInstruments
{
    /// <summary>
    /// 普源示波器通讯类
    /// </summary>
    public class DS1102 : IDisposable
    {
        #region 私有定义部分

        ///<summary>
        ///DS1102示波器，连接状态枚举类型
        ///</summary>
        private enum DS_Connect_Enum : byte
        {
            /// <summary>
            /// 未连接
            /// </summary>
            DisConnected = 0,
            /// <summary>
            /// 已连接
            /// </summary>
            Connected,
        }


        ///<summary>
        ///DS1102示波器，固定端口号
        ///</summary>
        private const int DS_Port_Num = 5555;


        //使用的全局变量,定义为静态变量，否则using结束后会被释放
        ///<summary>
        ///DS1102示波器，客户端Socket
        ///</summary>
        private static Socket DS_Socket_Client;
        ///<summary>
        ///DS1102示波器，连接并开始接收数据线程
        ///</summary>
        private static Thread DS_Connect_Thread;
        /// <summary>
        /// DS1102示波器，连接状态，初始未连接
        /// </summary>
        private static DS_Connect_Enum DS_Connect_Status = DS_Connect_Enum.DisConnected;
        /// <summary>
        /// DS1102示波器，接收数据缓冲区
        /// </summary>
        private static byte[] DS_Receive_Buffer = new byte[10000];
        /// <summary>
        /// DS1102示波器，接收数据长度
        /// </summary>
        private static int DS_Receive_Len = 0;

        /// <summary>
        /// DS1102示波器，通讯错误(硬件错误、超时、协议错误等)
        /// </summary>
        private const string DS_Error_Inf_Com = "DS1102示波器，通讯错误";
        /// <summary>
        /// DS1102示波器，数据错误(输入或返回的数据无效)
        /// </summary>
        private const string DS_Error_Inf_Data = "DS1102示波器，数据错误";
        /// <summary>
        /// DS1102示波器，设备错误(设备故障)
        /// </summary>
        private const string DS_Error_Inf_Device = "DS1102示波器，设备错误";  //暂时不用

        #endregion

        #region  公有定义部分

        /// <summary>
        /// DS1102示波器，开始运行/停止运行枚举类型
        /// 直接.tostring()发送命令
        /// </summary>
        public enum DS_Run_Enum : byte
        {
            /// <summary>
            /// 停止运行
            /// </summary>
            STOP = 0,
            /// <summary>
            /// 开始运行
            /// </summary>
            RUN,
        }

        /// <summary>
        /// DS1102示波器，水平时间档位枚举类型
        /// 值转换为double/1e9,转换为string发送命令
        /// </summary>
        public enum DS_Time_Scal_Enum : ulong
        {
            _2ns = 2,
            _5ns = 5,
            _10ns = 10,
            _20ns = 20,
            _50ns = 50,
            _100ns = 100,
            _200ns = 200,
            _500ns = 500,
            _1us = (ulong)1e3,
            _2us = (ulong)2e3,
            _5us = (ulong)5e3,
            _10us = (ulong)10e3,
            _20us = (ulong)20e3,
            _50us = (ulong)50e3,
            _100us = (ulong)100e3,
            _200us = (ulong)200e3,
            _500us = (ulong)500e3,
            _1ms = (ulong)1e6,
            _2ms = (ulong)2e6,
            _5ms = (ulong)5e6,
            _10ms = (ulong)10e6,
            _20ms = (ulong)20e6,
            _50ms = (ulong)50e6,
            _100ms = (ulong)100e6,
            _200ms = (ulong)200e6,
            _500ms = (ulong)500e6,
            _1s = (ulong)1e9,
            _2s = (ulong)2e9,
            _5s = (ulong)5e9,
            _10s = (ulong)10e9,
            _20s = (ulong)20e9,
            _50s = (ulong)50e9,
        }

        /// <summary>
        /// DS1102示波器，键盘锁枚举类型
        /// 直接.tostring()发送命令
        /// </summary>
        public enum DS_KeyBoard_Lock_Enum : byte
        {
            /// <summary>
            /// 键盘锁定关闭，面板可以操作
            /// </summary>
            OFF = 0,
            /// <summary>
            /// 键盘锁定打开，面板不能操作
            /// </summary>
            ON,
        }


        /// <summary>
        /// DS1102示波器，触发模式枚举类型，自动/普通/单次
        /// 直接.tostring()发送命令
        /// </summary>
        public enum DS_Trig_Mode : byte
        {
            /// <summary>
            /// 自动触发
            /// </summary>
            AUTO = 0,
            /// <summary>
            /// 普通触发
            /// </summary>
            NORM,
            /// <summary>
            /// 单次触发
            /// </summary>
            SING,
        }

        /// <summary>
        /// DS1102示波器，触发耦合方式枚举类型
        /// 直接.tostring()发送命令
        /// </summary>
        public enum DS_Trig_Coup : byte
        {
            /// <summary>
            /// 交流方式
            /// </summary>
            AC = 0,
            /// <summary>
            /// 直流方式
            /// </summary>
            DC,
        }


        /// <summary>
        /// DS1102示波器，边沿触发类型枚举类型
        /// 直接.tostring()发送命令
        /// </summary>
        public enum DS_Trig_Slop : byte
        {
            /// <summary>
            /// 上升沿触发
            /// </summary>
            POS = 0,
            /// <summary>
            /// 下降沿触发
            /// </summary>
            NEG,
            /// <summary>
            /// 上升沿或下降沿触发
            /// </summary>
            RFAL,

        }

        
        /// <summary>
        /// DS1102示波器，查询的参数枚举类型
        /// 直接.tostring()发送命令
        /// </summary>
        public enum DS_Query_Item_Enum : byte
        {
            /// <summary>
            /// 波形电压最大值
            /// </summary>
            VMAX = 0,
            /// <summary>
            /// 波形电压最小值
            /// </summary>
            VMIN,
            /// <summary>
            /// 波形电压峰峰值
            /// </summary>
            VPP,
            /// <summary>
            /// 波形电压平均值
            /// </summary>
            VAVG,
            /// <summary>
            /// 波形电压有效值
            /// </summary>
            VRMS,
            /// <summary>
            /// 波形频率
            /// </summary>
            FREQ,
        }


        /// <summary>
        /// DS1102示波器，通道号枚举类型
        /// 直接.tostring()发送命令
        /// </summary>
        public enum DS_Channel_Enum : byte
        {
            /// <summary>
            /// 通道1
            /// </summary>
            CHAN1 = 1,
            /// <summary>
            /// 通道2
            /// </summary>
            CHAN2,
        }


        /// <summary>
        /// DS1102示波器，通道开关枚举类型
        /// 直接.tostring()发送命令
        /// </summary>
        public enum DS_Channel_On_Enum : byte
        {
            /// <summary>
            /// 通道打开
            /// </summary>
            OFF = 0,
            /// <summary>
            /// 通道关闭
            /// </summary>
            ON,
        }


        /// <summary>
        /// DS1102示波器，通道耦合方式枚举类型
        /// 直接.tostring()发送命令
        /// </summary>
        public enum DS_Channel_Coup_Enum : byte
        {
            /// <summary>
            /// 交流方式
            /// </summary>
            AC = 0,
            /// <summary>
            /// 直流方式
            /// </summary>
            DC,
            /// <summary>
            /// 地方式
            /// </summary>
            GND,
        }


        /// <summary>
        /// DS1102示波器，通道带宽限制枚举类型
        /// 判断，转换为string，发送命令
        /// </summary>
        public enum DS_Channel_Bwl_Enum : byte
        {
            /// <summary>
            /// 带宽限制关闭
            /// </summary>
            _OFF = 0,
            /// <summary>
            /// 20M带宽限制
            /// </summary>
            _20M,
        }


        /// <summary>
        /// DS1102示波器，通道探头比设置枚举类型
        /// 转换为byte,再转换为string，发送命令
        /// </summary>
        public enum DS_Channel_Prob_Enum : byte
        {
            /// <summary>
            /// 通道探头比为1
            /// </summary>
            _1 = 1,
            /// <summary>
            /// 通道探头比为10
            /// </summary>
            _10 = 10,
        }


        /// <summary>
        /// DS1102示波器，通道垂直电压档位枚举类型
        /// 值转换为double/1e3,转换为string，发送命令
        /// </summary>
        public enum DS_Channel_Scal_Enum : int
        {
            /// <summary>
            /// 探头比1才有的
            /// </summary>
            _1mv = 1,
            /// <summary>
            /// 探头比1才有的
            /// </summary>
            _2mv = 2,
            /// <summary>
            /// 探头比1才有的
            /// </summary>
            _5mv = 5,
            _10mv = 10,
            _20mv = 20,
            _50mv = 50,
            _100mv = 100,
            _200mv = 200,
            _500mv = 500,
            _1v = (int)1e3,
            _2v = (int)2e3,
            _5v = (int)5e3,
            _10v = (int)10e3,
            /// <summary>
            /// 探头比10才有的
            /// </summary>
            _20v = (int)20e3,
            /// <summary>
            /// 探头比10才有的
            /// </summary>
            _50v = (int)50e3,
            /// <summary>
            /// 探头比10才有的
            /// </summary>
            _100v = (int)100e3,
        }

        #endregion

        #region 私有函数

        /// <summary>
        /// DS1102示波器，连接并开始接收数据线程函数；
        /// 连接状态通过全局变量DS_Connect_Status来查询；
        /// 接收数据及长度存放在DS_Receive_buffer，DS_Receive_Len中；
        /// </summary>
        /// <param name="ip_address">为ip地址</param>
        /// <param name="port_num">为端口号</param>
        private static void DS_Connect_Thread_fun(string ip_address, int port_num)
        {
            IPAddress ip = IPAddress.Parse(ip_address);   //IP地址
            int port = Convert.ToInt32(port_num);         //端口号
            IPEndPoint ipe = new IPEndPoint(ip, port);    //新建网络端点

            DS_Socket_Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  //新建socket通讯

            while (true)
            {
                try
                {
                    DS_Socket_Client.Connect(ipe);    //连接服务器，(阻塞直到连接上，或close(),或超时20秒左右)
                    while (false) ;
                }
                catch (Exception e)   //异常情况，0：网线没插、服务器端未打开，引发异常；1：my_socket_client.Close()引发异常
                {
                    string error = e.ToString();
                    goto end_sub;   //退出
                }

                if (DS_Socket_Client.Connected == true) break;   //如果连接上服务器，跳出

                Thread.Sleep(10);
            }

            //已链接上服务器
            DS_Connect_Status = DS_Connect_Enum.Connected;   //连接状态，已连接

            //开始接收数据
            while (true)
            {
                int len = 0;   //单次接收数据长度
                byte[] buffer = new byte[10000];   //接收数据缓冲区
                try
                {
                    len = DS_Socket_Client.Receive(buffer);   //数据长度及数据读取，会在此阻塞，直到有数据或者是断开连接
                }
                catch (Exception e)  //异常情况，0、服务器端断开连接，1：my_socket_client.Close()引发异常
                {
                    string error = e.ToString();

                    goto end_sub;  //退出
                }

                if (len > 0)   //有数据接收
                {
                    int a;
                    for (a = 0; a < len; a++)
                    {
                        if (DS_Receive_Len + a < 10000) DS_Receive_Buffer[DS_Receive_Len + a] = buffer[a];   //DS1102接收缓冲区载入数据
                    }

                    DS_Receive_Len += len;         //DS1102接收数据长度赋值
                }
                else    //服务器端断开连接
                {
                    goto end_sub;    //退出
                }

                Thread.Sleep(10);
            }

        end_sub: while (false) ;
            DS_Connect_Status = DS_Connect_Enum.DisConnected;   //连接状态，未连接

            //关闭客户端，断开连接，防止异常
            try { DS_Socket_Client.Close(); }                     //关闭客户端
            catch (Exception e) { string error_inf = e.ToString(); }

            try { DS_Socket_Client.Disconnect(true); }            //断开连接 
            catch (Exception e) { string error_inf = e.ToString(); }
        }


        /// <summary>
        /// DS1102示波器，发送命令
        /// </summary>
        /// <param name="ip_address">为ip地址</param>
        /// <param name="command">为发送的命令</param>
        /// <param name="error_inf">为错误信息,空为成功，否则为错误信息</param>
        private void DS_Write_Command(string ip_address, string command, out string error_inf)
        {
            error_inf = "";   //错误信息,空为成功，否则为错误信息
            int a = 0;        //用于循环

            byte[] buffer = Encoding.ASCII.GetBytes(command);   //字符串转换为数组
            int len = buffer.Length;         //需要发送的数据长度
            int send_len = 0;                //实际发送的数据长度

            //发送数据前清空缓冲区数据
            for (a = 0; a < DS_Receive_Buffer.Length; a++) DS_Receive_Buffer[a] = 0;   //DS1102清接收缓冲区数据
            DS_Receive_Len = 0;                                                        //DS1102清接收数据长度

            //如果DS1102没有连接，则先连接
            if (DS_Connect_Status == DS_Connect_Enum.DisConnected) DS_Connect(ip_address, out error_inf);
            if (error_inf != "")  //连接错误
            {
                goto ng_end_sub;
            }

            //尝试发送数据
            try
            {
                Thread.Sleep(10);        //延时10ms，防止连续通讯异常
                send_len = DS_Socket_Client.Send(buffer);  //发送数据
                if (send_len != len) goto ng_end_sub;
            }
            catch (Exception e)
            {
                string error = e.ToString();
                goto ng_end_sub;
            }
            goto end_sub;

        ng_end_sub: while (false) ;
            error_inf = DS_Error_Inf_Com;  //DS1102示波器，通讯错误，网口错误
            DS_DisConnect();               //DS1102示波器，断开连接函数，强制结束DS1102_Connect_Thread_fun线程函数

        end_sub: while (false) ;
        }


        /// <summary>
        /// DS1102示波器，读取数据(只接收返回十进制数据，否则错误)
        /// </summary>
        /// <param name="error_inf">为错误信息,空为成功，否则为错误信息</param>
        /// <returns>返回读取的十进制数据</returns>
        private decimal DS_Read_Data(out string error_inf)
        {
            error_inf = "";             //为错误信息,空为成功，否则为错误信息
            decimal read_data = 0;      //返回的十进制数据
            string buffer_string = "";  //缓冲区字符串
            byte[] buffer = null;       //缓冲区数据
            int len = 0;        //本次缓冲区数据长度
            int len_last = 0;   //上次缓冲区数据长度

            int a = 0;   //用于循环

            //等待数据接收完成,最长等50*10ms
            for (a = 0; a < 50; a++)
            {
                len = DS_Receive_Len;   //本次缓冲区数据长度赋值
                if (len > 0 && len == len_last) goto next_sub;
                len_last = len;         //上次缓冲区数据长度赋值

                Thread.Sleep(10);       //延时10ms
            }
            error_inf = DS_Error_Inf_Com;   //DS1102示波器，通讯错误，回复超时错误
            goto end_sub;

        next_sub: while (false) ;

            buffer = DS_Receive_Buffer;                        //将数据装入
            Array.Resize(ref buffer, DS_Receive_Len - 1);      //重定义有效的数据,去掉尾部的\n
            buffer_string = Encoding.UTF8.GetString(buffer);   //数据转换为字符串

            try
            {
                read_data = (decimal)Convert.ToDouble(buffer_string);    //数据转换,指数型数据不能直接转换为decimal
            }
            catch (Exception e)
            {
                string error = e.ToString();
                error_inf = DS_Error_Inf_Data;   //DS1102示波器，数据错误，回复数据无效
            }

        end_sub: while (false) ;
            return read_data;
        }
        
        #endregion
      
        #region 公有函数


        /// <summary>
        /// DS1102示波器，连接函数
        /// </summary>
        /// <param name="ip_address">为ip地址</param>
        /// <param name="error_inf">为错误信息,空为成功，否则为错误信息</param>
        public void DS_Connect(string ip_address, out string error_inf)
        {
            int a;           //用于循环
            error_inf = "";  //错误信息,空为成功，否则为错误信息

            if (DS_Connect_Status == DS_Connect_Enum.DisConnected)
            {
                if (DS_Connect_Thread == null)  //线程为空
                {
                    DS_Connect_Thread = new Thread(() => DS_Connect_Thread_fun(ip_address, DS_Port_Num));   //带参数的线程，DS1102连接并开始接收数据线程
                    DS_Connect_Thread.Name = "连接DS1102线程";
                    DS_Connect_Thread.Priority = ThreadPriority.Normal;
                    DS_Connect_Thread.IsBackground = true;
                    DS_Connect_Thread.Start();
                }
                else   //线程不为空
                {
                    if (DS_Connect_Thread.ThreadState == ThreadState.Stopped)  //线程状态停止
                    {
                        DS_Connect_Thread = new Thread(() => DS_Connect_Thread_fun(ip_address, DS_Port_Num));   //带参数的线程
                        DS_Connect_Thread.Name = "连接DS1102线程";
                        DS_Connect_Thread.Priority = ThreadPriority.Normal;
                        DS_Connect_Thread.IsBackground = true;
                        DS_Connect_Thread.Start();
                    }
                }
            }
            else goto end_sub;

            //等待连接,最长等待50*10ms
            for (a = 0; a < 50; a++)
            {
                if (DS_Connect_Status == DS_Connect_Enum.Connected) goto end_sub;
                Thread.Sleep(10);    //延时10ms
            }
            error_inf = DS_Error_Inf_Com;   //DS1102示波器，通讯错误，连接超时
            DS_DisConnect();        //DS1102示波器断开连接函数，强制结束DS1102_Connect_Thread_fun线程函数
            Thread.Sleep(100);      //延时100ms，等待线程结束

        end_sub: while (false) ;
        }


        /// <summary>
        /// DS1102示波器，断开连接函数,此处无需错误信息
        /// </summary>
        public void DS_DisConnect()
        {
            try { DS_Socket_Client.Close(); }                     //关闭客户端
            catch (Exception e) { string error_inf = e.ToString(); }

            try { DS_Socket_Client.Disconnect(true); }            //断开连接 
            catch (Exception e) { string error_inf = e.ToString(); }
        }

        
        /// <summary>
        /// DS1102示波器，启动自动设置
        /// </summary>
        /// <param name="ip_address">为ip地址</param>
        /// <param name="error_inf">为错误信息,空为成功，否则为错误信息</param>
        public void DS_Set_Auto_Test(string ip_address, out string error_inf)
        {
            error_inf = "";   //错误信息,空为成功，否则为错误信息
            
            string command = ":AUT\n";                          //命令，启动波形自动功能设置
            DS_Write_Command(ip_address, command, out error_inf);   //DS1102示波器发送命令
        }

        
        /// <summary>
        /// DS1102示波器，全局设置，(和通道、触发无关的设置)
        /// </summary>
        /// <param name="ip_address">为ip地址</param>
        /// <param name="run">为开始运行或停止运行</param>
        /// <param name="time_scale">为水平时间档位</param>
        /// <param name="kb_lock">为键盘锁</param>
        /// <param name="error_inf">为错误信息,空为成功，否则为错误信息</param>
        public void DS_Global_Set(string ip_address, DS_Run_Enum run, DS_Time_Scal_Enum time_scale, DS_KeyBoard_Lock_Enum kb_lock, out string error_inf)
        {
            error_inf = "";        //错误信息,空为成功，否则为错误信息
            string send_command;   //为发送的命令

            //DS1102示波器发送命令，开始运行、停止运行设置
            send_command = ":" + run.ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，水平时间档位设置
            send_command = ":TIM:MAIN:SCAL " + ((double)time_scale / 1e9).ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，键盘锁设置
            send_command = ":SYST:LOCK " + kb_lock.ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            end_sub: while (false) ;
        }

        
        /// <summary>
        /// DS1102示波器，边沿触发设置
        /// </summary>
        /// <param name="ip_address">为ip地址</param>
        /// <param name="mode">为触发模式，自动、普通、单次</param>
        /// <param name="coup">为触发耦合方式</param>
        /// <param name="channel">为触发源通道</param>
        /// <param name="slop">为触发类型，上升沿、下降沿等</param>
        /// <param name="level">为触发电平</param>
        /// <param name="">为错误信息,空为成功，否则为错误信息</param>
        public void DS_Edge_Trig_set(string ip_address, DS_Trig_Mode mode, DS_Trig_Coup coup, DS_Channel_Enum channel, DS_Trig_Slop slop, decimal level, out string error_inf)
        {
            error_inf = "";        //错误信息,空为成功，否则为错误信息
            string send_command;   //为发送的命令

            //DS1102示波器发送命令，触发模式设置
            send_command = ":TRIG:SWE " + mode.ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，触发耦合类型设置
            send_command = ":TRIG:COUP " + coup.ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，边沿触发类型设置，固定设置
            send_command = ":TRIG:MODE EDGE " + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，边沿触发源设置
            send_command = ":TRIG:EDG:SOUR " + channel.ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，边沿触发类型设置
            send_command = ":TRIG:EDG:SLOP " + slop.ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，边沿触发电平设置
            send_command = ":TRIG:EDG:LEV " + level.ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            end_sub: while (false) ;
        }

        
        /// <summary>
        /// DS1102示波器，执行指定参数的查询操作
        /// </summary>
        /// <param name="ip_address">为ip地址</param>
        /// <param name="channel">为查询的通道</param>
        /// <param name="para">为查询的参数枚举类型</param>
        /// <param name="error_inf">为错误信息,空为成功，否则为错误信息</param>
        /// <returns>返回指定参数类型的数据</returns>
        public decimal DS_Query_Value(string ip_address, DS_Channel_Enum channel, DS_Query_Item_Enum para, out string error_inf)
        {
            error_inf = "";           //错误信息,空为成功，否则为错误信息
            decimal query_data = 0;   //返回数据
            
            string Send_Command = ":MEAS:ITEM? " + para.ToString() + "," + channel.ToString() + "\n";   //发送命令计算
            DS_Write_Command(ip_address, Send_Command, out error_inf);   //DS1102示波器发送命令
            if (error_inf == "")
            {
                query_data = DS_Read_Data(out error_inf);   //DS1102示波器读取数据
            }

            return query_data;
        }




        /// <summary>
        /// DS1102示波器，通道设置
        /// </summary>
        /// <param name="ip_address">为ip地址</param>
        /// <param name="channel">为设置的通道</param>
        /// <param name="on">为通道开关</param>
        /// <param name="coup">为通道耦合方式</param>
        /// <param name="bwl">为通道带宽限制</param>
        /// <param name="prob">为通道探头比</param>
        /// <param name="scal">为垂直电压档位</param>
        /// <param name="offs">为垂直电压位移(档位小于0.5,-2~2)(档位大于0.5,-100~100)</param>
        /// <param name="error_inf">为错误信息,空为成功，否则为错误信息</param>
        public void DS_Channel_SET(string ip_address, DS_Channel_Enum channel, DS_Channel_On_Enum on, DS_Channel_Coup_Enum coup, DS_Channel_Bwl_Enum bwl, DS_Channel_Prob_Enum prob, DS_Channel_Scal_Enum scal, decimal offs, out string error_inf)
        {
            error_inf = "";       //为错误信息,空为成功，否则为错误信息
            string send_command;  //为发送的命令
            
            //DS1102示波器发送命令,通道开关
            send_command = ":" + channel.ToString() + ":DISP " + on.ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，耦合方式
            send_command = ":" + channel.ToString() + ":COUP " + coup.ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，带宽限制
            if (bwl == DS_Channel_Bwl_Enum._20M) send_command = ":" + channel.ToString() + ":BWL " + "20M" + "\n";
            else send_command = ":" + channel.ToString() + ":BWL " + "OFF" + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，通道探头比
            send_command = ":" + channel.ToString() + ":PROB " + ((byte)prob).ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，垂直电压档位
            send_command = ":" + channel.ToString() + ":SCAL " + ((double)scal / 1e3).ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;

            //DS1102示波器发送命令，垂直电压位移
            send_command = ":" + channel.ToString() + ":OFFS " + offs.ToString() + "\n";
            DS_Write_Command(ip_address, send_command, out error_inf);
            if (error_inf != "") goto end_sub;


            end_sub: while (false) ;
        }

        
        #endregion
        
        #region --垃圾回收机制

        //变量定义
        /// <summary>
        /// 是否已释放资源的标志
        /// </summary>
        private bool m_disposed = false;


        /// <summary>
        /// 释放内存中所占的资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);   //释放托管和非托管资源

            //将对象从垃圾回收器链表中移除，
            // 从而在垃圾回收器工作时，只释放托管资源，而不执行此对象的析构函数
            GC.SuppressFinalize(this);
        }



        /// <summary>
        /// 无法直接调用的资源释放函数
        /// </summary>
        /// <param name="disposing"></param>
        // 参数为true表示释放所有资源，只能由使用者调用
        // 参数为false表示释放非托管资源，只能由垃圾回收器自动调用
        // 如果子类有自己的非托管资源，可以重载这个函数，添加自己的非托管资源的释放
        // 但是要记住，重载此函数必须保证调用基类的版本，以保证基类的资源正常释放
        protected virtual void Dispose(bool disposing)
        {
            if (!m_disposed)
            {
                if (disposing)
                {
                    //释放托管资源   



                }

                //释放非托管资源        

                

                m_disposed = true;   //标志此对象已被释放
            }
        }


        /// <summary>
        /// 析构函数
        /// 由垃圾回收器调用，释放非托管资源
        /// </summary>
        ~DS1102()
        {
            Dispose(false);
        }

        #endregion





    }
}
